package com.gjy.rabbitmq.resolve;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * 提供可靠的连接配置和队列/交换机初始化
 *
 * @author gjy
 * @version 1.0
 * @since 2025-10-13 14:45:47
 */
@Getter
public class ReliableRabbitMQConfig {

    private static final Logger logger = LoggerFactory.getLogger(ReliableRabbitMQConfig.class);

    /**
     * RabbitMQ连接
     */
    private Connection connection;

    /**
     * RabbitMQ通道
     */
    private Channel channel;

    /**
     * 初始化可靠配置
     *
     * @throws IOException      连接异常
     * @throws TimeoutException 超时异常
     */
    public void initialize() throws IOException, TimeoutException {
        logger.info("开始初始化RabbitMQ可靠配置");

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 可靠性配置
        factory.setConnectionTimeout(30000);           // 连接超时30秒
        factory.setHandshakeTimeout(10000);           // 握手超时10秒
        factory.setRequestedHeartbeat(60);            // 心跳60秒
        factory.setAutomaticRecoveryEnabled(true);    // 启用自动恢复
        factory.setNetworkRecoveryInterval(10000);    // 网络恢复间隔10秒
        factory.setTopologyRecoveryEnabled(true);     // 启用拓扑恢复

        // 建立连接
        connection = factory.newConnection();
        channel = connection.createChannel();

        logger.info("RabbitMQ连接建立成功: host={}, port={}", factory.getHost(), factory.getPort());

        // 配置可靠性和持久化
        setupReliableConfiguration();

        logger.info("RabbitMQ可靠配置初始化完成");
    }

    /**
     * 设置可靠性配置
     *
     * @throws IOException 配置异常
     */
    private void setupReliableConfiguration() throws IOException {
        // 设置发布确认模式
        channel.confirmSelect();
        logger.debug("开启发布确认模式");

        // 声明持久化交换机
        channel.exchangeDeclare("reliable.exchange", BuiltinExchangeType.DIRECT, true);
        logger.debug("声明持久化交换机: reliable.exchange");

        // 配置死信队列
        setupDLXConfiguration();
    }

    /**
     * 配置死信队列
     *
     * @throws IOException 配置异常
     */
    private void setupDLXConfiguration() throws IOException {
        logger.info("开始配置死信队列");

        // 声明死信交换机
        channel.exchangeDeclare("dlx.exchange", BuiltinExchangeType.DIRECT, true);
        logger.debug("声明死信交换机: dlx.exchange");

        // 声明死信队列
        channel.queueDeclare("dlx.queue", true, false, false, null);
        logger.debug("声明死信队列: dlx.queue");

        // 绑定死信队列
        channel.queueBind("dlx.queue", "dlx.exchange", "dlx.routing.key");
        logger.debug("绑定死信队列: dlx.queue -> dlx.exchange (dlx.routing.key)");

        // 声明主队列，配置死信策略
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", "dlx.exchange");      // 死信交换机
        args.put("x-dead-letter-routing-key", "dlx.routing.key"); // 死信路由键
        args.put("x-message-ttl", 60000);                        // 消息过期时间60秒
        args.put("x-max-length", 10000);                         // 最大消息数量10000

        channel.queueDeclare("reliable.queue", true, false, false, args);
        logger.debug("声明主队列: reliable.queue");

        channel.queueBind("reliable.queue", "reliable.exchange", "reliable.routing.key");
        logger.debug("绑定主队列: reliable.queue -> reliable.exchange (reliable.routing.key)");

        logger.info("死信队列配置完成");
    }

    /**
     * 关闭连接和通道
     *
     * @throws IOException      关闭异常
     * @throws TimeoutException 超时异常
     */
    public void close() throws IOException, TimeoutException {
        logger.info("开始关闭RabbitMQ连接");

        if (channel != null && channel.isOpen()) {
            channel.close();
            logger.debug("通道已关闭");
        }

        if (connection != null && connection.isOpen()) {
            connection.close();
            logger.debug("连接已关闭");
        }

        logger.info("RabbitMQ连接关闭完成");
    }

}
